#include <iostream>
using namespace std;
#include <pthread.h>
#include <string>
#include <unistd.h>
#include "Cond.hpp"

// 测试一下条件变量的使用

// 1.全局条件变量
pthread_cond_t global_cond = PTHREAD_COND_INITIALIZER;

// 2.为了使用简单，直接使用全局锁
pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;


static int cnt = 1;


class ThreadDaTa{
public:
    ThreadDaTa(const string& name, myCond::Cond& cond)
        :_name(name),
        _cond(cond)
    {}

string _name;
myCond::Cond& _cond;    
};

// 在加锁的前提下进行同步操作，即不用再用sleep等函数来操控同步性了
void* Routine(void* args){
    ThreadDaTa* ptd = static_cast<ThreadDaTa*>(args); 

    // 每个线程不断地++cnt即可
    while(1){
        // pthread_mutex_lock(&global_lock);
        myMutex::Lock_Guard guard(ptd->_cond.GetMutex());


        // 在指定条件变量下进行等待
        //pthread_cond_wait(&global_cond, &global_lock);
        ptd->_cond.Wait();
        cout << ptd->_name << "线程 : " << "计算cnt的值___" << cnt++ << endl;
        //pthread_mutex_unlock(&global_lock);
    }

    return nullptr;
}



int main(){

    pthread_t tid1, tid2, tid3, tid4;

    /* pthread_create(&tid1, nullptr, Routine, (char*)"thread_1");
    pthread_create(&tid2, nullptr, Routine, (char*)"thread_2");
    pthread_create(&tid3, nullptr, Routine, (char*)"thread_3");
    pthread_create(&tid4, nullptr, Routine, (char*)"thread_4"); */

    myMutex::Mutex _mutex;
    myCond::Cond cond(_mutex);

    ThreadDaTa* td1 = new ThreadDaTa((char*)"thread_1", cond);
    ThreadDaTa* td2 = new ThreadDaTa((char*)"thread_2", cond);
    ThreadDaTa* td3 = new ThreadDaTa((char*)"thread_3", cond);
    ThreadDaTa* td4 = new ThreadDaTa((char*)"thread_4", cond);

    pthread_create(&tid1, nullptr, Routine, td1);
    pthread_create(&tid2, nullptr, Routine, td2);
    pthread_create(&tid3, nullptr, Routine, td3);
    pthread_create(&tid4, nullptr, Routine, td4);

    


    // 在指定条件变量下唤醒
    while(1){
        //pthread_cond_signal(&global_cond); // 一次唤醒一个
        cond.Signal();

        //pthread_cond_broadcast(&global_cond); // 一次唤醒全部等待的线程
        sleep(1);
    }

    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);
    pthread_join(tid4, nullptr);

    delete td1;
    delete td2;
    delete td3;
    delete td4;


    return 0;
}